﻿using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using TfsBranchLib2.Model;
using TfsComLib.TfsBranchLib2;

namespace TfsBranchLib2.View
{
    /// <summary>
    ///     Interaction logic for BranchSetComboBox.xaml
    ///     Control to select BranchSet
    /// </summary>
    public partial class BranchSetComboBox : UserControl
    {
        public static readonly DependencyProperty BranchSetsProperty =
            DependencyProperty.Register("BranchSets", typeof (BranchSetPrecedentContainer), typeof (BranchSetComboBox),
                new UIPropertyMetadata(null, OnChangePrecedentContainer));

        // Using a DependencyProperty as the backing store for SelectedValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedValueProperty =
            DependencyProperty.Register("SelectedValue", typeof (BranchSetItem), typeof (BranchSetComboBox),
                new UIPropertyMetadata(null, OnSelectedValueChanged));

        private readonly ObservableCollection<BranchSetItem> viewList = new ObservableCollection<BranchSetItem>();

        public BranchSetComboBox()
        {
            InitializeComponent();
            branchSetComboBox.SelectionChanged += branchSetComboBox_SelectionChanged;
            branchSetComboBox.DropDownOpened += branchSetComboBox_DropDownOpened;
            branchSetComboBox.ItemsSource = viewList;
        }

        public BranchSetPrecedentContainer BranchSets
        {
            get { return (BranchSetPrecedentContainer) GetValue(BranchSetsProperty); }
            set { SetValue(BranchSetsProperty, value); }
        }

        public BranchSetItem SelectedValue
        {
            get { return (BranchSetItem) GetValue(SelectedValueProperty); }
            set { SetValue(SelectedValueProperty, value); }
        }

        private void branchSetComboBox_DropDownOpened(object sender, EventArgs e)
        {
            UpdateBranchSetItemList(BranchSets);
        }

        public void UpdateBranchSetItemList(BranchSetPrecedentContainer branchSetPrecedentContainer)
        {
            Trace.WriteLine("BeginUpdate");
            if (branchSetPrecedentContainer != null)
            {
                var branchSetItem = branchSetComboBox.SelectedItem as BranchSetItem;
                branchSetComboBox.SelectedIndex = -1;
                viewList.Clear();
                viewList.Add(BranchSetItem.AllBranchesItem);
                BranchSetItem latest = null;
                var aggr =
                    branchSetPrecedentContainer.GetLatestAggregator();
                foreach (var item in branchSetPrecedentContainer.GetArrangedAggregators())
                {
                    var newBranchSetItem = new BranchSetItem
                    {
                        BranchSetValue = item,
                        ItemType = BranchSetItemType.Standard
                    };
                    viewList.Add(newBranchSetItem);
                    if (item == aggr)
                    {
                        latest = newBranchSetItem;
                    }
                }
                if ((branchSetItem == null) && (latest != null))
                {
                    branchSetItem = latest;
                }
                SetSelectedItem(branchSetItem);
            }
            else
            {
                branchSetComboBox.ItemsSource = null;
            }
            Trace.WriteLine("EndUpdate");
        }

        private void SetSelectedItem(BranchSetItem branchSetItem)
        {
            if (branchSetItem != null)
            {
                if (branchSetItem == BranchSetItem.AllBranchesItem)
                {
                    branchSetComboBox.SelectedItem = BranchSetItem.AllBranchesItem;
                }
                else
                {
                    foreach (var item in viewList)
                    {
                        if ((branchSetItem.BranchSetValue != null) && (item.BranchSetValue != null) &&
                            (item.BranchSetValue.PrecedentValue.Equals(branchSetItem.BranchSetValue.PrecedentValue)))
                        {
                            branchSetComboBox.SelectedItem = item;
                            break;
                        }
                    }
                }
            }
        }

        private void branchSetComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var item = branchSetComboBox.SelectedItem as BranchSetItem;
            if (item == null) SelectedValue = null;
            else SelectedValue = item;
        }

        private static void OnChangePrecedentContainer(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var branchSetComboBox = d as BranchSetComboBox;
            if (branchSetComboBox == null) return;
            var branchSetPrecedentContainer = e.NewValue as BranchSetPrecedentContainer;
            branchSetComboBox.UpdateBranchSetItemList(branchSetPrecedentContainer);
        }

        public event EventHandler SelectedValueChanged;

        private static void OnSelectedValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var branchSetComboBox = d as BranchSetComboBox;
            var newSelectedItem = e.NewValue as BranchSetItem;
            if ((branchSetComboBox == null) || (newSelectedItem == null)) return;
            branchSetComboBox.SetSelectedItem(newSelectedItem);
            if (branchSetComboBox.SelectedValueChanged != null)
                branchSetComboBox.SelectedValueChanged(branchSetComboBox, null);
        }
    }

    [ValueConversion(typeof (double), typeof (double))]
    internal class BranchSetComboBoxWidthConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var original = (double) value;
            return original - 1;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var original = (double) value;
            return original + 1;
        }

        #endregion
    }

    [ValueConversion(typeof (object), typeof (BranchSetItem))]
    internal class BranchSetObjectConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var item = value as BranchSetItem;
            if (item == null) return null;
            return item;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }

        #endregion
    }
}